/**
 * color draw up
 * Copyright (c) 2009 cmiscm.com
 * date of final modification : 2009. 11. 10 
*/
package com.cmiscm.utils.color
{
	import flash.display.BitmapData;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	/**
	 * Color draw out.
     * 
     */
	public class ColorDrawOut
	{
		/**
		 * Line draw out
		 * <p>
		 * 이미지의 색상을 라인으로 단순화 시킴
		 * @param $bit BitmapData
		 * @param $gap Line gap
		 * @return 
		 * 
		 * @example
     	 * <listing> 
     	 * package {
         *    import com.cmiscm.utils.color.ColorDrawOut;
         *    import flash.display.Bitmap;
         *    import flash.display.BitmapData;
         *    import flash.display.Sprite;
         *    import flash.geom.Rectangle;
         *    import flash.events.Event;
         *    
         *    public class TestColor extends Sprite
         *    {
         *        public function TestColor()
         *        {
         *             super();
         *             this.addEventListener(Event.ADDED_TO_STAGE, onAdd);
         *         }
         * 
         *         private function onAdd(evt:Event):void
         *         {
         *             evt.currentTarget.removeEventListener(evt.type, arguments.callee);
         * 
         *             var bitData:BitmapData = new imgTest(0, 0);
         *             var arr:Array = ColorDrawOut.lineDrawOut(bitData, 10);
         *            
         *             var bit_origin:Bitmap = new Bitmap(bitData);
         *             this.addChild(bit_origin);
         *            
         *             var bit_line:Bitmap = new Bitmap(new BitmapData(300, 154, false));
         *             bit_line.x = 305;
         *             var color:uint;
         *             var rect:Rectangle;
         *             var total:uint = arr.length;            
         *             for (var i:uint=0; i&lt;total; i++) {
         *                color = arr[i] as uint;
         *                rect = new Rectangle(10 * i, 0, 300, 154);
         *                bit_line.bitmapData.fillRect(rect, color);
         *             }
         *             this.addChild(bit_line);
         *        }
         *    }
         * }
         * </listing> 
		 * <p>
     	 * Result:</p>
     	 * <img src = "ColorPickUp0.jpg" />
		 */			
		public static function lineDrawOut($bit:BitmapData, $gap:int=10):Array
		{
			var coeX:int = $bit.width / $gap;
			var array:Array = [];
			var colorArr:Array;	
			var color:int;
			var copyBit:BitmapData = new BitmapData($gap, $bit.height, false);
			var rect:Rectangle;
			var point:Point = new Point();
			for (var i:int=0; i<coeX; i++) {
				rect = new Rectangle(i * $gap, 0, $gap, $bit.height);
				copyBit.copyPixels($bit, rect, point);
				colorArr = mostUsedColor(copyBit, 10);
				color = selectColor(colorArr);								
				array[i] = color;
			}			
			return array;
		}
		
		/**
		 * Draw out to most used color
		 * <br>
		 * 이미지에서 가장 많이 사용된 색상을 배열로 리턴
		 * @param $bit BitmapData
		 * @param $gap Pixel gap
		 * @param $quality 16, 32, 64
		 * @return 
		 * 
		 * @example
     	 * <listing> 
		 *	import com.cmiscm.utils.color.ColorDrawOut;
		 *	import flash.display.BitmapData;
		 *	import flash.display.Sprite;
		 *	
		 *	public class TestColor extends Sprite
		 *	{
		 *		public function TestColor()
		 *		{
		 *			var bitData:BitmapData = new imgTest(0, 0);
		 *			var arr:Array = ColorDrawOut.simplify(bitData, 10, 32);
		 *			trace(arr);
		 *		}
		 *	}
     	 * </listing> 
		 */		
		public static function mostUsedColor($bit:BitmapData, $gap:int=10, $quality:int=32):Array
		{
			var array:Array = [];
			var coeX:Number = $bit.width/($quality+1);
			var coeY:Number = $bit.height/($quality+1);
			var red:int;
			var green:int;
			var blue:int;
			var color16:int;
			var color8:int;
			var obj:Object = new Object();
			var k:int;
			for(var i:int=1; i<=$quality; i++) {
				for (k=1; k<=$quality; k++) {
					color16 = $bit.getPixel(coeX*i, coeY*k);
					red = ((color16 >> 20) << 4) | (color16 >> 20);
					green = ((color16 >> 12 & 0xF) << 4) | (color16 >> 12 & 0xF);
					blue = ((color16 >> 4 & 0xF) << 4) | (color16 >> 4 & 0xF);
					color8 = red << 16 | green << 8 | blue;
					if (obj[color8] == undefined) {
						array.push({color:color8, cnt:1});
						obj[color8] = array[array.length-1];
					} else {
						obj[color8].cnt++;
					}
				}
			}
			array.sortOn("cnt", Array.DESCENDING | Array.NUMERIC);			
			return arrayReduce(array, $gap);
		}
		
		private static function selectColor($arr:Array):uint
		{
			var color:uint;
			var total:int = $arr.length;
			for (var i:int=0; i<total; i++) {
				color = $arr[i];
				if (color != 0 && color != 16777215) break;
			}			
			return color;
		}
		
		private static function arrayReduce($array:Array, $gap:int):Array
		{
			var obj:Object;
			var color:int;
			var fix_array:Array = [];
			var flag:Boolean;
			for each(obj in $array) {
				flag = true;
				for each(color in fix_array) {					
					if(Math.abs((obj.color >> 20) - (color >> 20)) + Math.abs((obj.color >> 12 & 0xF) - (color >> 12 & 0xF)) + Math.abs((obj.color >> 4 & 0xF) - (color >> 4 & 0xF)) < $gap) {
						flag = false;
						break;
					}
				}
				if (flag) fix_array.push(obj.color);
			}
			return fix_array;
		}

	}
}